> -- | Diese Modul implementiert Datentypen fuer die interne Darstellung von CHF-Ausdruecken und Typen
> module CHF.CoreL.Language where
> import Data.List
> import Data.Char
> import Data.Maybe

> -- | Der Datentyp 'TDef' stellt (monomorphe) Datentypdefinitionen dar 

> data TDef tname cname = TDef tname [(cname,Type tname)]
>                        
>  deriving(Eq,Show)

> -- | Der Datentyp 'Type' stellt Typen dar.

> data Type tname 
>   -- | Typkonstruktoren, z.B. @ ListInt  = TC \"ListInt\" @
>   =  TC tname 
>   -- | Funktionstypen, z.B. @ Bool -> ListInt = (TC \"Bool\") :->: (TC \"ListInt\") @ 
>   | (Type tname) :->: (Type tname)
>   -- | Variablen (nur fuer die Typherleitung notwendig)
>   | TVar String
>   -- | IO-Typen
>   | TIO (Type tname)
>   -- | MVARTypen
>   | TMVar (Type tname)
>  deriving(Ord,Eq,Show)

> -- | outType berechnet den Ergebnistyp eines Funktionstypen

> outType :: Type t -> Type t
> outType (t1 :->: t2) = outType t2
> outType t = t

> toType [x] = x
> toType (x:xs) = x :->: (toType xs)


> -- | der Datentyp 'Expr' dient der Darstellung von CHF-Ausdruecken.
> --   Er ist polymorph ueber einer Markierung label und ueber dem
> --   Typ fuer Konstruktornamen und dem Typ fuer Variablennamen definiert.

> data Expr label cname v =
>   -- | Variable: x = @ Var \"x\" @
>     Var v                        
>   -- | Abstraktion: \x -> e = @ Lam \"x\" e @
>   | Lam v (Expr label cname v)
>   -- | Applikation: (e1 e2) = @ App e1 e2 @
>   | App (Expr label cname v) (Expr label cname v)
>   -- | seq-Ausdruck: seq e1 e2 = @ Seq e1 e2 @
>   | Seq (Expr label cname v) (Expr label cname v)
>   -- | Konstruktor-Applikation: (c e1 ... en) = @ Cons (Right \"c\") [e1,...,en] @
>   --   Beachte die Verwendung von Right
>   --   'Left' ist reserviert fuer die Monadischen Operatoren (s.u.)
>   | Cons (Either MAction cname) [Expr label cname v]
>   -- | Case-Ausdruck: case e of {Alt1;...;Altn} = @ Case e [Alt1,...,Altn] @
>   | Case (Expr label cname v) [CAlt label cname v]
>   -- | Letrec-Ausruck: letrec x1=e1;...;xn=en in e = @ Letrec [x1 :=: e1,...,xn :=: en] e @
>   | Letrec [Binding label cname v] (Expr label cname v)
>   -- | Label: Wird benutzt, um einen bel. Label um einen Ausdruck zu packen
>   | Label label (Expr label cname v)
>  deriving(Eq,Show)

> -- | Der Datentyp 'MAction' stellt die verschiedenen monadischen Operationen dar
> --   Beachte die Darstellung der Monadischen Operationen innerhalb des 'Expr'-Typs:
> --   Sie werden als Konstruktorapplikationen mit Left dargestellt, d.h.:
> -- 
> --   * @ forkIO e      --> Cons (Left Fork) [e] @
> -- 
> --   * @ return e      --> Cons (Left Return) [e] @
> -- 
> --   * @ takeMVar e    --> Cons (Left Take) [e] @
> -- 
> --   * @ putMVar e1 e2 --> Cons (Left Put) [e1,e2] @
> -- 
> --   * @ newMVar e     --> Cons (Left New) [e] @
> -- 
> --   * @ e1 >>= e2     --> Cons (Left Bind) [e1,e2] @
> -- 
> -- Beachte: Fuer diese Konstruktoren kann man kein case konstruieren!

> data MAction 
>  = Fork   -- ^ fuer forkIO
>  | Return -- ^ fuer return
>  | Take   -- ^ fuer takeMVar
>  | Put    -- ^ fuer putMVar
>  | New    -- ^ fuer newMVar
>  | Bind   -- ^ fuer den >>= Operator
>  deriving(Eq,Show)


> -- | 'showMaction' berechnet den String zu einer 'MAction'

> showMaction :: MAction -> String
> showMaction (Fork) = "forkIO"
> showMaction (Return) = "return"
> showMaction (Take) = "takeMVar"
> showMaction (Put) = "putMVar"
> showMaction (Bind) = "(>>=)"
> showMaction (New) = "newMVar"


> -- | Der Datentyp 'CAlt' stellt case-Alternativen dar

> data CAlt label cname v = 
>  -- | Case-Alternative (c x1 ... xn) -> e  = CAlt "c" [x1,...,xn] e
>  CAlt cname [v] (Expr label cname v)
>  deriving(Eq,Show)

> -- | Der Datentyp 'Binding' stellt eine letrec-Bindung dar

> data Binding label cname v = 
>  -- | letrec-Bindung: x=e  =  x :=: e
>  v :=: (Expr label cname v)
>  deriving(Eq,Show)


